import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import BaseShift from '@main/entities/service/admin/base/base-shift.entity';
import BaseShiftUser from '@main/entities/service/admin/base/base-shift-user.entity';
import { In, Like, Not, Repository } from 'typeorm';
import SysUser from '@main/entities/service/admin/sys/sys-user.entity';
import { BaseWorkTypeService } from '@main/service/modules/admin/base/workType/workType.service';
import BaseWorkType from '@main/entities/service/admin/base/base-work-type.entity';
import { ApiException } from '@main/common/exceptions/api.exception';
import { SysOperationLogService } from '../../system/operationLog/operationLog.service';

@Injectable()
export class BaseShiftService {
  constructor(
    @InjectRepository(SysUser) private userRepository: Repository<SysUser>,
    @InjectRepository(BaseShift) private shiftRepository: Repository<BaseShift>,
    @InjectRepository(BaseShiftUser)
    private shiftUserRepository: Repository<BaseShiftUser>,
    @InjectRepository(BaseWorkType)
    private workTypeRepository: Repository<BaseWorkType>,
    private baseWorkTypeService: BaseWorkTypeService,
    private operationLogService: SysOperationLogService
  ) {}

  /**
   * 列举所有角色：除去超级管理员
   */
  async list() {
    const shiftList = await this.shiftRepository.find();

    await Promise.all(
      shiftList.map(async (shift) => {
        const { shiftCode } = shift;
        const userList = await this.shiftUserRepository.find({ where: { shiftCode } });

        await Promise.all(
          userList.map(async (user) => {
            const obj = await this.userRepository.findOne({ where: { id: user.userId } });

            if (obj) {
              user['nickName'] = obj.nickName;
            }
          })
        );

        shift['userList'] = userList;
      })
    );

    return shiftList;
  }

  /**
   * 分页加载班组信息
   */
  async page(data) {
    const { pageSize, pageNum, entity = {} } = data;

    const { shiftName = '', shiftCode = '' } = entity;

    return await this.shiftRepository.findAndCount({
      where: {
        shiftName: Like(`%${shiftName}%`),
        shiftCode: Like(`%${shiftCode}%`),
      },
      order: {
        updateTime: 'DESC',
      },
      take: pageSize,
      skip: (pageNum - 1) * pageSize,
    });
  }

  async checkUserIdBindShiftCode(userList, shiftCode) {
    let result = true;

    for (let i = 0; i < userList.length; i++) {
      const obj = await this.shiftUserRepository.findOne({
        where: {
          userId: userList[i].userId,
          shiftCode: Not(shiftCode),
        },
      });

      if (obj) {
        result = false;

        return false;
      }
    }

    return result;
  }

  /**
   * 处理岗位逻辑，如果是新增岗位，则调用岗位新增方法
   */
  async handleWorkType(userList, user, mac, ip, syncHostSqlite) {
    const workTypeList = [
      ...new Set(
        userList.map((item) => {
          const { workTypeCode, workTypeName } = item;
          return JSON.stringify({
            workTypeCode,
            workTypeName,
          });
        })
      ),
    ].map((item) => JSON.parse(item as string));
    for (let i = 0; i < workTypeList.length; i++) {
      const { workTypeCode } = workTypeList[i];
      const result = await this.workTypeRepository.findOne({ where: { workTypeCode } });
      if (!result)
        await this.baseWorkTypeService.add(workTypeList[i], user, mac, ip, syncHostSqlite);
    }
  }

  /**
   * 增加班组
   */
  async add(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const { shiftCode, shiftName, remark, userList } = data;

    await this.handleWorkType(userList, user, mac, ip, syncHostSqlite);

    const shift = await this.shiftRepository.insert({
      shiftCode,
      shiftName,
      remark,
      createName: user.nickName,
      createUserName: user.userName,
      updateName: user.nickName,
      updateUserName: user.userName,
    });
    databaseOperationLogList.push({
      type: 'add',
      dataType: 'obj',
      database: 'BaseShift',
      checkOnlyKeyList: [],
      data: shift,
      whereObj: null,
      remark: `BaseShift表新增数据`,
    });
    await this.operationLogService.add(
      {
        type: 'add',
        msg: `班组管理模块新增班组`,
        databaseOperationLogList,
        remark: `新增班组${data.shiftName}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );

    if (userList && userList.length > 0) {
      await this.isExistKey1(userList, shiftCode);

      // const result = await this.checkUserIdBindShiftCode(userList, shiftCode);

      // if (!result) {
      //   // return IpcErrorException('新增人员已绑定班组')
      //   // 新增人员已绑定班组

      //   throw new ApiException(10026);
      // }

      // 关联菜单
      const insertRows = userList.map((m) => {
        return {
          shiftCode,
          ...m,
        };
      });
      const shiftUser = await this.shiftUserRepository.insert(insertRows);
      databaseOperationLogList.push({
        type: 'add',
        dataType: 'obj',
        database: 'BaseShiftUser',
        checkOnlyKeyList: [],
        data: shiftUser,
        whereObj: null,
        remark: `BaseShiftUser表新增数据`,
      });
      await this.operationLogService.add(
        {
          type: 'add',
          msg: `班组管理模块人员列表新增数据`,
          databaseOperationLogList,
          remark: `新增人员`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );
    }
  }

  /**
   * 更新班组信息
   */
  async update(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const { id, shiftName, shiftCode, remark, userList } = data;

    await this.handleWorkType(userList, user, mac, ip, syncHostSqlite);

    await this.shiftRepository.update(
      { id },
      {
        shiftName,
        shiftCode,
        remark,
        updateName: user.nickName,
        updateUserName: user.userName,
      }
    );
    databaseOperationLogList.push({
      type: 'update',
      dataType: 'obj',
      database: 'BaseShift',
      checkOnlyKeyList: [],
      data: {
        shiftName,
        shiftCode,
        remark,
        updateName: user.nickName,
        updateUserName: user.userName,
      },
      whereObj: { id },
      remark: `BaseShift表更新班组信息`,
    });
    await this.operationLogService.add(
      {
        type: 'update',
        msg: `班组管理模块更新班组信息`,
        databaseOperationLogList,
        remark: `更新班组${data.shiftName}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );

    if (userList && userList.length) {
      await this.isExistKey1(userList, shiftCode);
      // const result = await this.checkUserIdBindShiftCode(userList, shiftCode);

      // if (!result) {
      //   // return IpcErrorException('新增人员已绑定班组')
      //   // 新增人员已绑定班组

      //   throw new ApiException(10026);
      // }
      await this.shiftUserRepository.delete({ shiftCode });
      databaseOperationLogList.push({
        type: 'delete',
        dataType: 'array',
        database: 'BaseShiftUser',
        checkOnlyKeyList: [],
        data: null,
        whereObj: null,
        remark: `BaseShiftUser表删除人员`,
      });
      await this.operationLogService.add(
        {
          type: 'delete',
          msg: `班组管理模块人员列表删除人员`,
          databaseOperationLogList,
          remark: `删除人员`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );

      const shiftUser = await this.shiftUserRepository.insert(
        userList.map((item) => ({ ...item, shiftCode }))
      );
      databaseOperationLogList.push({
        type: 'add',
        dataType: 'obj',
        database: 'BaseShiftUser',
        checkOnlyKeyList: [],
        data: shiftUser,
        whereObj: null,
        remark: `BaseShiftUser表新增数据`,
      });
      await this.operationLogService.add(
        {
          type: 'add',
          msg: `班组管理模块人员列表新增数据`,
          databaseOperationLogList,
          remark: `新增人员`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );
    }
  }

  /**
   * 根据Id数组删除班组
   */
  async delete(idList, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const shiftList = await this.shiftRepository.find({
      where: {
        id: In(idList),
      },
    });

    for (let i = 0; i < shiftList.length; i++) {
      const { shiftCode } = shiftList[i];
      await this.shiftUserRepository.delete({ shiftCode });
      databaseOperationLogList.push({
        type: 'delete',
        dataType: 'array',
        database: 'BaseShiftUser',
        checkOnlyKeyList: [],
        data: null,
        whereObj: shiftCode,
        remark: `BaseShiftUser表删除人员`,
      });
      await this.operationLogService.add(
        {
          type: 'delete',
          msg: `班组管理模块人员列表删除人员`,
          databaseOperationLogList,
          remark: `删除人员`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );
    }

    await this.shiftRepository.delete(idList);
    databaseOperationLogList.push({
      type: 'delete',
      dataType: 'array',
      database: 'BaseShift',
      checkOnlyKeyList: [],
      data: null,
      whereObj: idList,
      remark: `BaseShift表删除班组`,
    });
    await this.operationLogService.add(
      {
        type: 'delete',
        msg: `班组管理模块删除班组`,
        databaseOperationLogList,
        remark: `删除班组`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  /**
   * 根据id获取班组信息
   */
  async info(id) {
    const shift = await this.shiftRepository.findOne({
      where: { id },
    });

    if (shift) {
      const { shiftCode } = shift;

      const userList = await this.shiftUserRepository.find({ where: { shiftCode } });

      shift['userList'] = userList;

      return shift;
    }
  }

  async isExistKey(shiftCode: string) {
    const result = await this.shiftRepository.findOne({ where: { shiftCode } });

    if (result) throw new ApiException(10027);
  }

  async isExistKey1(userList, shiftCode: string) {
    const result = await this.checkUserIdBindShiftCode(userList, shiftCode);

    if (!result) {
      // return IpcErrorException('新增人员已绑定班组')
      // 新增人员已绑定班组
      throw new ApiException(10026);
    }
  }
}
